﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace DCT.CodeBox.EventTrigger.Codes
{
    /// <summary>
    /// 事件触发器
    /// </summary>
    /// <typeparam name="TArgument">时间传递参数</typeparam>
    public class EventTrigger<TArgument>
    {
        /// <summary>
        /// 监听事件，Func返回值，如果返回false，则中断后面的所有事件；返回true则继续执行
        /// </summary>
        private List<Func<TArgument, bool>> listeners;

        /// <summary>
        /// 提供暴露给其他参数添加监听的属性
        /// </summary>
        public EventTriggerListener<TArgument> OutsideListener { get; private set; }

        /// <summary>
        /// 永远返回true
        /// </summary>
        private static Predicate<Func<TArgument, bool>> AlwaysReturnTrue = delegate { return true; };

        /// <summary>
        /// 不公开构造函数，使用CreateInstance产生
        /// </summary>
        private EventTrigger()
        {
            //初始化监听集合
            this.listeners = new List<Func<TArgument, bool>>();
            //初始化监听的属性
            this.OutsideListener = new EventTriggerListener<TArgument>(listeners);
        }       

        /// <summary>
        /// 触发事件
        /// </summary>
        /// <param name="arg">事件参数</param>
        /// <returns>true为全部执行完毕；false为执行过break</returns>
        public bool Fire(TArgument arg)
        {
            return this.Fire(AlwaysReturnTrue, arg);
        }

        /// <summary>
        /// 触发事件
        /// </summary>
        /// <param name="predicate">过滤事件</param>
        /// <param name="arg">事件参数</param>
        /// <returns>true为全部执行完毕；false为执行过break</returns>
        public bool Fire(Predicate<Func<TArgument, bool>> predicate, TArgument arg)
        {
            if (predicate == null)
            {
                throw new NullReferenceException("predicate is null");
            }
            lock (this.listeners)
            {
                foreach (var item in this.listeners)
                {
                    if (predicate(item))
                    {
                        bool iscontinue = item(arg);
                        if (!iscontinue)
                        {
                            return false;
                        }
                    }
                }
            }
            return true;
        }

        /// <summary>
        /// 异步触发事件，此时Func返回的bool已经无效
        /// </summary>
        /// <param name="predicate">过滤事件</param>
        /// <param name="arg">事件参数</param>
        /// <returns>是否全部进入队列正常运行</returns>
        public bool InvokeFire(Predicate<Func<TArgument, bool>> predicate, TArgument arg)
        {
            if (predicate == null)
            {
                throw new NullReferenceException("predicate is null");
            }
            bool isAllQueueSucc = true;
            lock (this.listeners)
            {
                foreach (var item in this.listeners)
                {
                    if (predicate(item))
                    {
                        //这步必须设置一个变量存储item；
                        //如果直接在QueueUserWorkItem委托内用item，由于是异步，item在foreach一直在变，因此QueueUserWorkItem引用的item就很有可能不正确
                        Func<TArgument, bool> tmpAction = item; 
                        bool queue = ThreadPool.QueueUserWorkItem(delegate(object _obj)
                        {
                            tmpAction((TArgument)_obj);
                        }, arg);
                        if (!queue && isAllQueueSucc)
                        {
                            isAllQueueSucc = false;
                        }
                    }
                }
            }
            return isAllQueueSucc;
        }

        /// <summary>
        /// 异步触发事件，此时Func返回的bool已经无效
        /// </summary>
        /// <param name="arg">事件参数</param>
        /// <returns>是否全部进入队列正常运行</returns>
        public bool InvokeFire( TArgument arg)
        {
            return this.InvokeFire(AlwaysReturnTrue, arg);
        }

        /// <summary>
        /// 清除所有监听
        /// </summary>
        public void Clear()
        {
            lock (this.listeners)
            {
                this.listeners.Clear();
            }
        }

        /// <summary>
        /// 创建实例
        /// </summary>
        /// <returns></returns>
        public static EventTrigger<TArgument> CreateInstance()
        {
            return new EventTrigger<TArgument>();
        }
    }
}
